package http;

import core.ByteBuf;

import java.nio.charset.StandardCharsets;

public class HttpResponse extends HttpMessage{
    public  String code;
    public  String status;

    public HttpResponse(){
        this.code="200";
        this.status="OK";
    }
    public HttpResponse(String code,String status){
        this.code=code;
        this.status=status;
    }

    public static String getReason(int code) {
        switch (code) {
            case 301:
                return "Moved Permanently";
            case 302:
                return "Moved Temporary";
            case 400:
                return "Bad Request";
            case 401:
                return "Unauthorized";
            case 403:
                return "Forbidden";
            case 404:
                return "Not Found";
            case 405:
                return "Method Not Allowed";
            case 406:
                return "Not Acceptable";
            case 408:
                return "Request Timeout";
            case 409:
                return "Conflict";
            case 410:
                return "Gone";
            case 413:
                return "Request Entity Too Large";
            case 414:
                return "Request-URI Too Long";
            case 415:
                return "Unsupported Media Type";
            case 429:
                return "Too Many Requests";
            case 500:
                return "Internal Server Error";
            case 501:
                return "Not Implemented";
            case 502:
                return "Bad Gateway";
            case 503:
                return "Service Unavailable";
            case 504:
                return "Gateway Timeout";
            case 505:
                return "HTTP Version Not Supported";
            default:
                return "Unknown Status Code";
        }
    }

    public int parse(byte[] bytes) {

        if(getHttpLength(bytes,charset) < 0) return -1;

        String data=new String(bytes,charset);

        data=clearMessage(data);

        int posFirstLine=data.indexOf(newLine);
        if (posFirstLine!=-1){
            if (!parseFirstLine(data.substring(0,posFirstLine))) return -1;
        }
        else {
            return posFirstLine;
        }

        String strHeader,strContent;
        int posHeader=data.indexOf(newLine+newLine);
        if (posHeader==-1){
            strHeader=data;
            strContent="";
        }
        else {
            strHeader=data.substring(0,posHeader);
            strContent=data.substring(posHeader+2*newLine.length());
        }
        getHeaderField(strHeader.substring(posFirstLine+newLine.length()),this.header);

        if (checkNoContent(data)) return 0;

        return parseContent(this.header,strContent,charset,byteBuf);
    }

    public boolean parseFirstLine(String firstLine) {
        //HTTP/1.1 200 OK

        int posMethod=firstLine.indexOf("HTTP/");
        if (posMethod==-1) return false;

        int posCode=firstLine.indexOf(" ",posMethod);
        if (posCode==-1) return false;

        this.httpVersion=firstLine.substring(posMethod+"HTTP/".length(),posCode);

        int posStatus=firstLine.indexOf(" ",posCode);
        if (posStatus==-1) return false;

        this.code=firstLine.substring(posCode+1,posStatus);
        this.status=firstLine.substring(posStatus+1);

        return true;
    }

    public byte[] buildMessage() {
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("HTTP/")
                .append(httpVersion)
                .append(" ")
                .append(this.code)
                .append(" ")
                .append(this.status)
                .append(newLine);

        header.forEach((key, value) -> {
            stringBuilder.append(key)
                    .append(": ")
                    .append(value.get(value.size() - 1))
                    .append(newLine);
        });

        stringBuilder.append(newLine);
        System.out.println(stringBuilder.toString());

        ByteBuf buf=new ByteBuf();
        buf.put(stringBuilder.toString().getBytes(charset));

        if (byteBuf.getCanReadSize()>0) {
            byte[] bytes = byteBuf.get();
            buf.put(bytes);
        }

        return buf.get();
    }

    public static String buildErrorMessage(int code) {
        String str=getReason(code);
        return String.format("HTTP/1.1 %d %s\r\nContent-Length: %d\r\nContent-Type: text/html;charset=UTF-8\r\n\r\n%s",code,str,str.getBytes(StandardCharsets.UTF_8).length,str);
    }

    public static String buildRedirectMessage(int code,String redirectUri) {
        String str=getReason(code);
        return String.format("HTTP/1.1 %d %s\r\nContent-Length: %d\r\nContent-Type: text/html;charset=UTF-8\r\nLOCATION: %s\n\r\n%s",code,str,str.getBytes(StandardCharsets.UTF_8).length,redirectUri,str);
    }

}
